package xing.design.pattern.behavioral.Memento.sample1;

/**
 * Originator 即需要要做备份的类。
 * <p>
 * 将备份操作交给其自己。
 * <p>---<p>
 * <b>关于 Originator 接口：</b>
 * <p>
 * 我们发现， 由于 Memento 接口的适用性，对任意的 Originator 都可以用，因此可以有
 * <p>
 * 一个 Originator 接口与之对应。
 *
 * @author xing
 * @date 2023/2/10 1:45:53
 */
public class BaseOriginator implements Originator {
    private String info;

    /**
     * 创建备份
     */
    @Override
    public Memento createSnapshot() {
        // 如果 BaseMemento 不是 static class，就算将 createSnapshot 放其中，
        // 返回 this 还是 clone()?
        // 那我这里直接 new 不就好了。为啥还要调用 createSnapshot 呢。、
        // 如果完全将方法放入 BaseMemento 中，对本类的对象的调用者，
        // 方法会对外、对其不可见，人家不知道可以 createSnapshot，还得自行 new BaseMemento() ，太难用
        return new BaseMemento(this.info);
    }

    /**
     * 恢复备份，错误（不好的）案例
     * <p>
     * restore 没必要放在这里，
     * <p>
     * 这里势必要传入 BaseMemento 对象，但对外暴露的是 Memento 接口，
     * <p>
     * 假如实现类增加，这里，传入的 Memento 类型就可能有误。二者对不上。
     * <p>
     * 而放入 Memento 类中，可以保证，恢复的是对应的 Originator 类。
     * <p>
     * 如果在这里，既要保证 originator 类的正确，是想要恢复的类，还要保证 Memento 的对应。
     * <p>
     * 当然，如果本身保证没其他实现类，或者本身就不整接口，都不整，那开心就好吧。（Originator 应该不会对应多个 Memento 实现吧，没必要啊。）你可以说我要吧修改自身属性的留在内部，啊，行。（其实被使用本身就会被外部改变，不然做啥备份，这点并没必要争取。）
     */
    @Override
    @Deprecated
    public boolean restore(Memento memento) {
        if (memento instanceof BaseMemento) {
            this.info = ((BaseMemento) memento).info;
            return true;
        }
        return false;
    }

    /**
     * 备份类，存储要被备份的内容。以及包含了恢复操作。
     * <p>
     * 作为内部类，对外 人家不好用，最好有一个暴露的（窄）接口。
     * <p>
     * 作为内部类，应该是类自己要用的，起码在这里对外没必要暴露。
     * <p>
     * 不过如果需要外部确认类型，那就需要暴露出去。
     * <p>
     * （参考 Java 的 {@link java.util.ArrayList ArrayList} 的 {@link java.util.ArrayList.Itr Iterator} 接口 与 {@link java.util.ArrayList.ListItr ListIterator} 的实现，也是如此的。）
     */
    private class BaseMemento implements Memento {
        /**
         * 对于复杂对象，也可以流的方式将类存为 String 放入 String 中。
         */
        private final String info;

        private BaseMemento(String info) {
            this.info = info;
        }

        @Override
        public void restore() {
            BaseOriginator.this.info = this.info;
        }
    }

    // ----------- getter and setter -----------

    public String getInfo() {
        return this.info;
    }

    public void setInfo(String info) {
        this.info = info;
    }


}

